package org.example.cloudapply.service;

import lombok.extern.slf4j.Slf4j;
import org.example.cloudapply.config.WechatConfig;
import org.example.cloudapply.dto.ApplicationDTO;
import org.example.cloudapply.entity.*;
import org.example.cloudapply.repository.ApplicationRepository;
import org.example.cloudapply.repository.ScheduleJobRepository;
import org.example.cloudapply.repository.UserRepository;
import org.example.cloudapply.vo.ApplicationDetailVO;
import org.example.cloudapply.vo.ApplicationVO;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@Service
public class ApplicationService {

    private final UserRepository userRepository;
    private final ApplicationRepository applicationRepository;
    private final ScheduleJobRepository scheduleJobRepository;
    private final WechatService wechatService;
    private final WechatConfig wechatConfig;
    public ApplicationService(UserRepository userRepository, ApplicationRepository applicationRepository, org.example.cloudapply.repository.ScheduleJobRepository scheduleJobRepository, WechatService wechatService, WechatConfig wechatConfig) {
        this.userRepository = userRepository;
        this.applicationRepository = applicationRepository;
        this.scheduleJobRepository = scheduleJobRepository;
        this.wechatService = wechatService;
        this.wechatConfig = wechatConfig;
    }

    @Transactional
    public void processApplication(ApplicationDTO dto) {

        // 处理用户信息
        User user = convertToUser(dto);
        User existingUser = userRepository.findByOpenid(dto.getOpenid());

        if (existingUser == null) {
            userRepository.insert(user);
        } else {
            user.setUserId(existingUser.getUserId());
            userRepository.update(user);
        }

        // 创建申请记录
        Application application = new Application();
        application.setUserId(user.getUserId());
        application.setTemplateId(dto.getTemplateId());
        application.setGpuEnabled(dto.getGpuEnabled());
        application.setCloudType(dto.getCloudType());
        application.setUserId(user.getUserId());
        application.setName(dto.getName());
        application.setRole(dto.getRole());
        application.setSchoolId(dto.getSchoolId());
        application.setEmail(dto.getEmail());
        application.setPhone(dto.getPhone());
        application.setStatus(ApplicationStatus.pending);
        // 计算到期时间
        application.setExpireTime(calculateExpireTime(dto.getDurationDays()));
        application.setDurationDays(dto.getDurationDays());
        applicationRepository.insert(application);
        // 创建定时任务
        createScheduleJobs(application);
    }

    private User convertToUser(ApplicationDTO dto) {
        User user = new User();
        user.setOpenid(dto.getOpenid());
        return user;
    }

    public List<ApplicationVO> getApplicationsByOpenid(String openid) {
        List<Application> applications = applicationRepository.findByOpenid(openid);
        return applications.stream().map(app -> {
            ApplicationVO vo = new ApplicationVO();
            vo.setApplyId(app.getApplyId());
            vo.setCloudType(app.getCloudType().name());
            vo.setStatus(app.getStatus().name());
            vo.setApplyTime(app.getApplyTime());
            vo.setHandleTime(app.getHandleTime());
            vo.setRejectReason(app.getRejectReason());
            vo.setAccountInfo(app.getAccountInfo());
            return vo;
        }).collect(Collectors.toList());
    }

    public void cancelApplication(Integer applyId) {
        int affected = applicationRepository.cancelApplication(applyId);

    }
    public void deleteScheduleJobsByApplyId(Integer applyId) {
        int affected = applicationRepository.deleteScheduleJobsByApplyId(applyId);
    }
    //计算到期时间
    private LocalDateTime calculateExpireTime(Integer durationDays) {
        LocalDateTime now = LocalDateTime.now();
        return now.plusDays(durationDays);
    }
    // 创建定时任务
    private void createScheduleJobs(Application application) {
        // 提前7天提醒
        ScheduleJob remindJob = new ScheduleJob();
        remindJob.setApplyId(application.getApplyId());
        remindJob.setJobType("reminder");
        remindJob.setTriggerTime(application.getExpireTime().minus(7, ChronoUnit.DAYS));
        scheduleJobRepository.createJob(remindJob);

        // 提前3天提醒
        ScheduleJob remindJob3 = new ScheduleJob();
        remindJob3.setApplyId(application.getApplyId());
        remindJob3.setJobType("reminder");
        remindJob3.setTriggerTime(application.getExpireTime().minus(3, ChronoUnit.DAYS));
        scheduleJobRepository.createJob(remindJob3);

        // 到期回收
        ScheduleJob recycleJob = new ScheduleJob();
        recycleJob.setApplyId(application.getApplyId());
        recycleJob.setJobType("recycle");
        recycleJob.setTriggerTime(application.getExpireTime());
        scheduleJobRepository.createJob(recycleJob);
    }

    // 新增定时任务处理
    @Scheduled(cron = "0 0 0 * * ?", zone = "Asia/Shanghai")
    public void processScheduledJobs() {
        List<ScheduleJob> jobs = scheduleJobRepository.findPendingApprovedJobs();
        System.out.println("aaggfhfghcfgy");
        jobs.forEach(job -> {
            try {
                boolean success = false;
                if ("reminder".equals(job.getJobType())) {
                    sendReminder(job.getApplyId());
                    System.out.println("whwh");
                    success = true;
                } else if ("recycle".equals(job.getJobType())) {
                    System.out.println("jkkkkkkkkkkkkkk");
                    sendReminder(job.getApplyId());
                    recycleResources(job.getApplyId());
                    success = true;
                }

                if(success) {
                    scheduleJobRepository.updateJobStatus(job.getJobId(), "completed");
                }
            } catch (Exception e) {
                scheduleJobRepository.updateJobStatus(job.getJobId(), "failed");
                log.error("定时任务处理失败，任务ID：{}", job.getJobId(), e);
            }
        });
    }
    //发送即将到期的订阅消息
    private void sendReminder(Integer applyId) {
        ApplicationDetailVO detail = applicationRepository.findDetailById(applyId);
        if (detail == null || detail.getExpireTime() == null) return;

        try {
            Map<String, String> content = new HashMap<>();
            long daysLeft = ChronoUnit.DAYS.between(LocalDateTime.now(), detail.getExpireTime());

            content.put("thing9", "云资源到期提醒");
            content.put("thing4", String.format("%s %d核%dG%s剩余%d天",
                    detail.getCloudType(),
                    detail.getCpuCores(),
                    detail.getMemoryGb(),
                    detail.getGpuEnabled() ? "+GPU" : "",
                    daysLeft
            ));
            content.put("time11", detail.getExpireTime()
                    .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")));

            wechatService.sendSubscribeMessage(
                    detail.getOpenid(),
                    wechatConfig.getReminderTemplateId(), // 需在配置新增提醒模板ID
                    content
            );
        } catch (Exception e) {
            log.error("到期提醒发送失败，申请ID：{}", applyId, e);
        }
    }
    //调用api进行自动释放资源
    private void recycleResources(Integer applyId) {
        ScheduleJob job = scheduleJobRepository.updateJobStatusByApplyId(applyId, "recycle");
        if (job == null) return;

        try {
            // 调用云平台API释放资源
            // cloudService.recycleInstance(app.getAccountInfo());

            // 标记定时任务状态
            scheduleJobRepository.updateJobStatus(job.getJobId(), "completed");
        } catch (Exception e) {
            scheduleJobRepository.updateJobStatus(job.getJobId(), "failed");
            log.error("资源回收失败，申请ID：{}", applyId, e);
        }
    }


}